﻿using DotNumerics.LinearAlgebra.CSLapack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Orthogonal Matching Pursuit

namespace FaceRecognition
{
    class OMP
    {
        int _signalLength; // dlugosc sygnalu - ilosc zdjec
        int _samplesCount; // ilosc probek 
        int _iterations = 0; // ilosc iteracji

        double[,] _PHI; // macierz pomiaru
        double[,] _PHIt; // macierz do ktorej wstaiwamy potem istotne kolumny macierzy PHI
        double[] _vec;
        double[] _x;
        double[] _xt;

        public double[] xt
        {
            get
            {
                return _xt;
            }
            set
            {
            }
        }

        public OMP(double[,] A, double[] y, int it)
        {
            _PHI = A;
            _PHIt = new double [A.GetLength(0),A.GetLength(1)];
            Matrix.MatrixZeros(_PHIt);
            _vec = y;
            _x = Matrix.MatrixVectorMultiply(Matrix.MatixTranspose(A), y);
            _xt = new double[_x.Length];
            Matrix.VectorZeros(_xt);

            _signalLength = A.GetLength(1);
            _samplesCount = y.Length;
            _iterations = it;
        }

        public void processOMPMethod()
        {
            DotNumerics.LinearAlgebra.Matrix lsResult = null;
            double[] v = copyVector(_vec);
            double[] r= copyVector(v); // residuum

            double max = 0;
            int max_ind = 0;
            double temp;

            int[] perm;
            int rem,toogle;
            List<int> LAMBDA = new List<int>(); //zbior indeksow istotnych kolumn macierzy PHI
            List<int> ind = new List<int>();

            for (int i = 0; i < _iterations; i++)
            {
                max = 0;
                max_ind = 0;

                for (int j = 0; j < _signalLength; j++) 
                {
                    if(!LAMBDA.Contains(j))
                    {
                        temp = Math.Abs(Matrix.Dot(r,Matrix.MatrixGetColumn(_PHI,j))); 
                        if ( temp > max)  //szukamy kolumny dajacej najwiekszy iloczyn skalarny
                        {    
                            max = temp;
                            max_ind = j;
                            rem = j; // ta kolumne trzeba usunac z listy ind, zeby juz w kolejnej petli nie brac jej pod uwage
                        }
                    }
                }

                LAMBDA.Add(max_ind);

                Matrix.MatrixAddColumns(_PHI, _PHIt, max_ind);


                int info = 0;
                
                //utworzenie nowego wektora do obliczenia metody najmniejszych kwadratów
                double[,] ret = Matrix.VectorToTwoDim(v);
                
     
                DotNumerics.LinearAlgebra.Matrix _phit = new DotNumerics.LinearAlgebra.Matrix(_PHIt);
                DotNumerics.LinearAlgebra.Matrix _v = new DotNumerics.LinearAlgebra.Matrix(ret);

                //metoda najmniejszych kwadratów
                DotNumerics.LinearAlgebra.LinearLeastSquares ls = new DotNumerics.LinearAlgebra.LinearLeastSquares();

                lsResult = ls.COFSolve(_phit, _v);

                DotNumerics.LinearAlgebra.Matrix at = _phit.Multiply(lsResult);

                //residuum
                r = Matrix.VectorDiff(v, at.GetColumnArray(0));
            }

            _xt = lsResult.GetColumnArray(0);

            DotNumerics.LinearAlgebra.Vector xxT = new DotNumerics.LinearAlgebra.Vector(_xt);
 

        }

        public double[] SCI(double[] xt)
        {
            double[] _sci = new double[ xt.Length];

            for (int i = 0; i < _sci.Length; i++)
            {


            }

            return _sci;
        }

        public double[] copyVector(double[] x)
        {
            double[] temp = new double[x.Length];

            for (int i = 0; i < x.Length; i++)
            {
                temp[i] = x[i];
            }

            return temp;
        }
    }
}
